<html>
<head>
<meta http-equiv="Pragma" content="no-cache"/>
<meta http-equiv="Cache-Control" content="no-cache"/>
<meta http-equiv="Expires" content="-1" />
<title>Web Services - Sample 14: Multi-Origin with JavaScript API buffered commands</title>

<style><!--
a{text-decoration:none;
  padding: 1px;
  background-color: #dddddd}
--></style>

<script src="json2.js"></script> 
<script src="pymol.js"></script>

<script type="text/javascript">

// This page assumes that PyMOL is running on localhost:8084

var pymol = new PyMOL('localhost', 8084, 'on'); // create PyMOL instance with buffering enabled

var cmd = pymol.cmd; // assign a global symbol for the PyMOL cmd API

function part2(list) {
    for(var i=0;i<list.length;i++) {
        cmd.color("auto","chain "+list[i]);
    }
    pymol.flush()
}

function part1() {
    cmd.reinitialize();
    cmd.load("$PYMOL_PATH/test/dat/1tii.pdb");
    cmd.show_as("cartoon");
    cmd.get_chains(part2, "polymer");
}

</script>

</head>
<body>

<h3>Web Services - Sample 14:  Multi-Origin with JavaScript API buffered commands</h3>

<a href="http://localhost:8084/apply/_quit?href">quit pymol</a>

(FireFox only: <a href="javascript:void(0)" onclick="window.open('view-source:' + location.href)">view page source</a>)

<p>PyMOL should open up automatically when this page is loaded because
we have an hidden IFRAME referencing a PWG file which tells PyMOL
to launch and listen on port 8084.</p>

<p>As usual in the multi-origin scenario, the host and port of the
PyMOL server must be specified when creating the PyMOL object inside
JavaScript.  However, to enable buffering, we also add a third
argument: 'on'.</p>

<pre>
var pymol = new PyMOL('localhost', 8084, 'on'); // create PyMOL object with buffering enabled

var cmd = pymol.cmd; // assign a global symbol for the PyMOL cmd API
</pre>

<p>Enabling buffering prevents the problem where all PyMOL requests
run in an <i>undefined</i> order (in certain browsers).  However,
requests must still of course run asynchrously in order to work around
the same-origin policy.</p>

<p>The trick to using buffering in the multi-origin (cross-domain) scenario is to remember three things:</p>
<ol>

<li>PyMOL API calls are not actually invoked unless you provide a
callback function or call pymol.flush().</li>

<li>The value returned from the final method call is the argument
provided to the callback function.</li>

<li>Method invocation is asynchronous, but will be in-order and
completed by the time the callback is called.</li> </ol>

<p>So when you need to flush the buffer and force execution, you
simply provide a callback function, which will be called after all of
the prior requests have been evaluated.  This enables us to simplify
the burdensome example from Sample 12 with its four cascading
functions into just two functions.</p>

<pre>
function part2(list) {
    for(var i=0;i&lt;list.length;i++) {
        cmd.color("auto","chain "+list[i]);
    }
    pymol.flush()
}

function part1() {
    cmd.reinitialize();
    cmd.load("$PYMOL_PATH/test/dat/1tii.pdb");
    cmd.show_as("cartoon");
    cmd.get_chains(part2, "polymer");
}

Start the cascade with a call to <a href="javascript:part1()">part1()</a>
</pre>

<p>Note that we are considering adding a buffered mode to the PyMOL
JavaScript interface which would improve performance by reducing the
number of independent HTTP requests and provide an in-order-execution
guarantee for multiple requests even when running asynchronously
(under the multi-origin scenario).</p>

<p>Also, exceptions which occur in PyMOL are not presently returned to
the JavaScript layer (though this may change).</p>

<!-- the only purpose of this IFRAME is to launch PyMOL via the PWG
  -- helper mechanism -->

<iframe src="start8084.pwg"
 width="0" height="0" frameborder="0"
 marginheight="0" marginwidth="0"
 scrolling="auto"></iframe>

</body>
</html>
